import asyncio
import binascii
from bleak import BleakClient, BleakScanner
from loguru import logger
import time

from Uitl.AppLogger import AppLogger

# 定义所有带read权限的特征UUID及对应含义（按你的服务列表整理）
READABLE_CHAR_MAP = {
    # 电池服务（180f）
    "00002a19-0000-1000-8000-00805f9b34fb": "电池电量（0~100%）",
    # 通用属性服务（1801）
    "00002a05-0000-1000-8000-00805f9b34fb": "服务变更特征（系统级）",
    # 设备信息服务（180a）
    "00002a26-0000-1000-8000-00805f9b34fb": "固件版本",
    "00002a23-0000-1000-8000-00805f9b34fb": "系统ID",
    "00002a2a-0000-1000-8000-00805f9b34fb": "序列号",
    "00002a50-0000-1000-8000-00805f9b34fb": "PnP ID（即插即用标识）",
    "00002a24-0000-1000-8000-00805f9b34fb": "型号名称",
    "00002a28-0000-1000-8000-00805f9b34fb": "硬件版本",
    "00002a29-0000-1000-8000-00805f9b34fb": "厂商名称",
    "00002a27-0000-1000-8000-00805f9b34fb": "软件版本",
    "00002a25-0000-1000-8000-00805f9b34fb": "固件修订版本"
}

# 电池特征UUID单独提取（用于特殊解析）
BATTERY_LEVEL_CHAR_UUID = "00002a19-0000-1000-8000-00805f9b34fb"

# --------------------------
# 通用解析函数：根据特征类型解析值
# --------------------------
def parse_char_value(char_uuid, hex_value):
    """根据特征UUID解析16进制值为可读格式"""
    char_name = READABLE_CHAR_MAP.get(char_uuid, f"未知可读特征（UUID: {char_uuid}）")

    # 1. 电池电量特殊解析（0~100%）
    if char_uuid == BATTERY_LEVEL_CHAR_UUID:
        try:
            # 蓝牙标准：1字节无符号整数（0~100）
            battery_percent = int(hex_value, 16)  # 直接将16进制转整数（hex_value是"00"→0，"50"→80）
            return f"{char_name}: {battery_percent}%", hex_value
        except Exception:
            return f"{char_name}: 解析失败", hex_value

    # 2. 其他特征：优先尝试ASCII转码（设备信息多为字符串）
    try:
        ascii_str = binascii.unhexlify(hex_value).decode("ascii", errors="replace")
        # 去除无效字符（如果有）
        clean_str = ascii_str.replace("\x00", "").strip()
        return f"{char_name}: {clean_str}", hex_value
    except Exception:
        # 非ASCII格式（二进制数据），直接返回原始16进制
        return f"{char_name}: 二进制数据", hex_value

# --------------------------
# 读取所有带read权限的特征（核心逻辑）
# --------------------------
async def read_all_specified_readable_chars(client, services):
    print("\n" + "=" * 60)
    print("【已读取所有带 'read' 权限的特征（按你的服务列表）】")
    print("=" * 60)

    # 遍历所有服务和特征，只处理带read权限的
    for service in services:
        print(f"\n📋 服务 UUID: {service.uuid}")
        print(f"   服务说明: {get_service_description(service.uuid)}")

        for char in service.characteristics:
            # 只处理标有read权限的特征
            if "read" in char.properties:
                try:
                    # 读取特征值（bytes→16进制字符串）
                    value_bytes = await client.read_gatt_char(char.uuid)
                    hex_value = value_bytes.hex()
                    # 解析值
                    parsed_value, raw_value = parse_char_value(char.uuid, hex_value)
                    print(f"  - 特征 UUID: {char.uuid}")
                    print(f"    特征含义: {READABLE_CHAR_MAP.get(char.uuid, '未知')}")
                    print(f"    解析结果: {parsed_value}")
                    print(f"    原始值（16进制）: {raw_value}")
                except Exception as e:
                    print(f"  - 特征 UUID: {char.uuid}")
                    print(f"    特征含义: {READABLE_CHAR_MAP.get(char.uuid, '未知')}")
                    print(f"    读取状态: 失败 → {str(e)}")
                print("  " + "-" * 40)

# --------------------------
# 辅助函数：获取服务说明（按你的服务列表）
# --------------------------
def get_service_description(service_uuid):
    service_map = {
        "0000180f-0000-1000-8000-00805f9b34fb": "电池服务（Battery Service）",
        "0000ffe0-0000-1000-8000-00805f9b34fb": "自定义数据传输服务（厂商常用）",
        "00001801-0000-1000-8000-00805f9b34fb": "通用属性服务（Generic Attribute Service）",
        "0000180a-0000-1000-8000-00805f9b34fb": "设备信息服务（Device Information Service）",
        "f000ffc0-0451-4000-b000-000000000000": "自定义数据传输服务（厂商常用）"
    }
    return service_map.get(service_uuid, "未知服务")

# --------------------------
# 主连接逻辑
# --------------------------
async def connect_to_ups():
    device_name = "UPS电池"

    print("正在扫描设备...")
    # 扫描包含指定名称的蓝牙设备
    device = await BleakScanner.find_device_by_filter(
        lambda d, ad: d.name and device_name in d.name,
        timeout=10.0
    )

    if not device:
        print("未找到UPS电池设备")
        return False

    print(f"找到设备: {device.address}")

    try:
        # 建立蓝牙连接
        async with BleakClient(device) as client:
            print("连接成功!")

            # 兼容不同版本的 Bleak，获取设备服务
            try:
                services = client.services
                print("使用新版 Bleak API")
            except AttributeError:
                services = await client.get_services()
                print("使用旧版 Bleak API")

            # 核心：读取所有带read权限的特征（按你的服务列表）
            await read_all_specified_readable_chars(client, services)

            return True

    except Exception as e:
        print(f"连接失败: {e}")
        return False

# --------------------------
# 循环运行主逻辑
# --------------------------
async def run_continuously():
    while True:
        try:
            success = await connect_to_ups()
            if success:
                print("等待60秒后再次读取...")
                await asyncio.sleep(60)  # 等待60秒后再次读取
            else:
                print("连接失败，等待10秒后重试...")
                await asyncio.sleep(10)  # 连接失败则等待10秒后重试
        except KeyboardInterrupt:
            print("用户中断程序")
            break
        except Exception as e:
            print(f"发生未预期错误: {e}")
            print("等待10秒后重试...")
            await asyncio.sleep(10)

if __name__ == "__main__":
    AppLogger("UPS")
    asyncio.run(run_continuously())
